package com.example.demo.controller;

import cn.dev33.satoken.stp.StpUtil;
import com.example.demo.constant.RedisConstant;
import com.example.demo.constant.SystemConstant;
import com.example.demo.constant.TaskConstant;
import com.example.demo.controller.bean.Result;
import com.example.demo.dto.CommodityDTO;
import com.example.demo.dto.CommodityInfoDTO;
import com.example.demo.dto.CreateOrderDTO;
import com.example.demo.dto.RankDTO;
import com.example.demo.exception.CommodityNotFoundException;
import com.example.demo.exception.StockDeductionException;
import com.example.demo.exception.ZeroStockException;
import com.example.demo.mapper.StudentClothingMapper;
import com.example.demo.mapper.entity.*;
import com.example.demo.service.*;
import com.example.demo.utils.CouponsUtil;
import com.example.demo.utils.PageBo;
import com.example.demo.utils.PageVo;
import com.example.demo.utils.RedisUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.time.Duration;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * @author Lucy
 * @create 2024-02-17 12:47
 */
@RequestMapping("pointsMall")
@Api(value = "积分商城", tags = {"积分商城接口"})
@RestController
@Slf4j
public class PointsMallController {

    @Autowired
    private StudentCertificationService studentCertificationService;

    @Autowired
    private StudentPointsService studentPointsService;

    @Autowired
    private StudentCouponsService couponsService;

    @Autowired
    private StudentOrderService orderService;

    @Autowired
    private StudentClothingService clothingService;

    @Autowired
    private RedisUtil redisUtil;

    @ResponseBody
    @ApiOperation("获取积分商城头部的显示信息")
    @RequestMapping(value = "getPointsMallHead", method = {RequestMethod.POST,  RequestMethod.GET} )
    public Result<Object> getPointsMallHead(){
        int studentId = StpUtil.getLoginIdAsInt();
        Map<String, Object> map = new HashMap<>();
        int points = studentPointsService.selectStudentPointsByStudentId(studentId).getPoints();
        map.put("points", points);
        return Result.ok(map);
    }

    @ApiOperation("获取积分商城学习用品列表")
    @RequestMapping(value = "getLearningSuppliesList", method = {RequestMethod.POST})
    public Result<PageVo<CommodityDTO>> getLearningSuppliesList(@RequestBody PageBo pageBo){
        PageVo<CommodityDTO> learningSuppliesList =  studentPointsService.getCommoditiesList(pageBo, TaskConstant.POINTS_MALL_LEARNING_SUPPLIES);
        return Result.ok(learningSuppliesList);
    }

    @ApiOperation("获取积分商城生活用品列表")
    @RequestMapping(value = "getDailyNecessitiesList", method = {RequestMethod.POST})
    public Result<PageVo<CommodityDTO>> getDailyNecessitiesList(@RequestBody PageBo pageBo){
        PageVo<CommodityDTO> dailyNecessitiesList =  studentPointsService.getCommoditiesList(pageBo, TaskConstant.POINTS_MALL_DAILY_NECESSITIES);
        return Result.ok(dailyNecessitiesList);
    }

    @ApiOperation("获取积分商城优惠券列表")
    @RequestMapping(value = "getCouponsList", method = {RequestMethod.POST})
    public Result<PageVo<CommodityDTO>> getCouponsList(@RequestBody PageBo pageBo){
        PageVo<CommodityDTO> couponsList =  studentPointsService.getCouponsList(pageBo, TaskConstant.POINTS_MALL_COUPONS);
        return Result.ok(couponsList);
    }

    @ApiOperation("获取积分商城服饰列表")
    @RequestMapping(value = "getClothesList", method = {RequestMethod.POST})
    public Result<PageVo<CommodityDTO>> getClothesList(@RequestBody PageBo pageBo){
        int studentId = StpUtil.getLoginIdAsInt();
        Student currentStudent = studentCertificationService.selectStudentById(studentId);
        PageVo<CommodityDTO> clothesCommodityList =  studentPointsService.getCommoditiesList(pageBo, TaskConstant.POINTS_MALL_CLOTHING, currentStudent.getGender());
        return Result.ok(clothesCommodityList);
    }
    //注意：学习用品、生活用品和虚拟服饰共用这一个接口获取商品详情页的信息
    @ApiOperation("获取积分商城商品详情页信息")
    @GetMapping("/getCommodityInfo/{commodityId}")
    public Result<CommodityInfoDTO> getCommodityInfo(@PathVariable int commodityId) {
        Commodity commodity = studentPointsService.selectCommodityById(commodityId);
        CommodityInfoDTO commodityInfoDTO = new CommodityInfoDTO();
        commodityInfoDTO.setCommodityId(commodity.getCommodityId());
        commodityInfoDTO.setCommodityName(commodity.getCommodityName());
        commodityInfoDTO.setStock(commodity.getStock());
        commodityInfoDTO.setPointsRequired(commodity.getPointsRequired());
        commodityInfoDTO.setImageUrl(SystemConstant.aliyunOSSUrlPrefix + commodity.getImageUrl());
        commodityInfoDTO.setDescription(commodity.getDescription());
        return Result.ok(commodityInfoDTO);
    }

    @ApiOperation("获取积分商城优惠券详情页信息")
    @GetMapping("/getCouponInfo/{commodityId}")
    public Result<CommodityInfoDTO> getCouponInfo(@PathVariable int commodityId) {
        Commodity commodity = studentPointsService.selectCommodityById(commodityId);
        CommodityInfoDTO commodityInfoDTO = new CommodityInfoDTO();
        commodityInfoDTO.setCommodityId(commodity.getCommodityId());
        commodityInfoDTO.setCommodityName(commodity.getCommodityName());
        commodityInfoDTO.setStock(commodity.getStock());
        commodityInfoDTO.setPointsRequired(commodity.getPointsRequired());
        //优惠券没有图片，所以这里存放优惠券标签
        Coupons coupons = couponsService.selectCouponsById(commodity.getCouponsId());
        commodityInfoDTO.setImageUrl(CouponsUtil.generateCouponLabel(coupons));
        commodityInfoDTO.setDescription("优惠券说明："+coupons.getDescription()+"\n使用条件："+coupons.getCondition());
        return Result.ok(commodityInfoDTO);
    }

    //构建省市区三级联动选择器的接口在RegionController

    @ApiOperation("实物商品下单接口")
    @RequestMapping(value = "createPhysicalOrder", method = {RequestMethod.POST})
    public Result<String> createPhysicalOrder(@RequestBody CreateOrderDTO createOrderDTO){
        Commodity commodity = studentPointsService.selectCommodityById(createOrderDTO.getCommodityId());
        try {
            studentPointsService.updateCommodityStock(commodity); // 调用更新库存的方法
        } catch (StockDeductionException e) {
            return Result.warn(e.getMessage());
        } catch (ZeroStockException e) {
            return Result.warn(e.getMessage());
        } catch (CommodityNotFoundException e) {
            return Result.warn(e.getMessage());
        }
        int studentId = StpUtil.getLoginIdAsInt();
        studentPointsService.updateStudentPoints(studentId,0,commodity.getPointsRequired());
        Order order = new Order();
        order.setOrderNumber();
        order.setStudentId(studentId);
        order.setCommodityId(createOrderDTO.getCommodityId());
        order.setPointsUsed(createOrderDTO.getPointsUsed());
        order.setProvinceId(createOrderDTO.getProvinceId());
        order.setCityId(createOrderDTO.getCityId());
        order.setAreaId(createOrderDTO.getAreaId());
        order.setAddress(createOrderDTO.getAddress());
        order.setContactName(createOrderDTO.getContactName());
        order.setContactPhone(createOrderDTO.getContactPhone());
        if(createOrderDTO.getNotes()!=null){
            order.setNotes(createOrderDTO.getNotes());
        }
        order.setStatus(TaskConstant.ORDER_STATUS_WAIT);
        orderService.createOrder(order);
        return Result.ok("下单成功");
    }

    @ApiOperation("虚拟商品下单接口")
    @GetMapping("/createVirtualOrder/{commodityId}")
    public Result<String> createVirtualOrder(@PathVariable int commodityId){
        int studentId = StpUtil.getLoginIdAsInt();
        Commodity commodity = studentPointsService.selectCommodityById(commodityId);
        try {
            studentPointsService.updateCommodityStock(commodity); // 调用更新库存的方法
        } catch (StockDeductionException e) {
            return Result.warn(e.getMessage());
        } catch (ZeroStockException e) {
            return Result.warn(e.getMessage());
        } catch (CommodityNotFoundException e) {
            return Result.warn(e.getMessage());
        }
        studentPointsService.updateStudentPoints(studentId,0,commodity.getPointsRequired());
        if(commodity.getCategory() == TaskConstant.POINTS_MALL_CLOTHING){
            StudentClothing studentClothing = new StudentClothing();
            studentClothing.setStudentId(studentId);
            studentClothing.setClothingId(commodity.getClothingId());
            clothingService.insertStudentClothing(studentClothing);
        }else{
            couponsService.insertStudentCoupons(studentId, commodity.getCouponsId());
        }
        ExchangeRecord exchangeRecord = new ExchangeRecord();
        exchangeRecord.setStudentId(studentId);
        exchangeRecord.setCommodityId(commodityId);
        exchangeRecord.setPointsUsed(commodity.getPointsRequired());
        studentPointsService.insertExchangeRecord(exchangeRecord);
        return Result.ok("下单成功");
    }

    @ApiOperation("获取积分排行榜")
    @RequestMapping(value = "getLeaderboard", method = {RequestMethod.POST})
    public Result<Object> getLeaderboard(){
        int studentId = StpUtil.getLoginIdAsInt();
        Map<String, Object> map = new HashMap<>();
        List<RankDTO> topTenRankList = new ArrayList<>();
        Set<Object> topTenRank = redisUtil.top(RedisConstant.Student_Points_Rank_Name,10);
        int rankCount = 1;
        for(Object o : topTenRank){
            RankDTO dto = new RankDTO();
            Student student = studentCertificationService.selectStudentById((int) o);
            if(student == null){
                redisUtil.remove(RedisConstant.Student_Points_Rank_Name,o);
                continue;
            }
            dto.setRank(rankCount);
            dto.setStudentId((int) o);
            dto.setStudentName(student.getName());
            dto.setAvatar(SystemConstant.aliyunOSSUrlPrefix + student.getAvatar());
            dto.setPoints(studentPointsService.selectStudentPointsByStudentId((int) o).getTotalEarned());
            rankCount++;
            topTenRankList.add(dto);
        }
        map.put("topTenRank",topTenRankList);
        RankDTO dto = new RankDTO();
        long rank = redisUtil.getRankNum(RedisConstant.Student_Points_Rank_Name,studentId);
        Student student = studentCertificationService.selectStudentById(studentId);
        dto.setRank(rank);
        dto.setStudentId(studentId);
        dto.setStudentName(student.getName());
        dto.setAvatar(SystemConstant.aliyunOSSUrlPrefix + student.getAvatar());
        dto.setPoints(studentPointsService.selectStudentPointsByStudentId(studentId).getTotalEarned());
        map.put("currentStudentRank",dto);
        return Result.ok(map);
    }
}
